iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0

今天的主題:讓玩家知道怎麼玩,也知道發生了什麼

遊戲能打了、會輸會贏、有震動有紀錄。但昨天測試的時候我發現一件事:不輸入名字、不按出征,直接按攻擊也能玩。

而畫面上明明寫著「請先輸入名字,然後按下出征!」。

規格與實作不一致

這種問題在測試工作裡很常見,而且比單純的 bug 更麻煩 —— 因為你得先決定哪一邊才是對的。

那行字到底是「必填說明」還是「友善建議」?程式從來沒有表態。

兩條路都說得通:

做法 理由
改程式:沒出征就不能攻擊 文字說了必填,就該真的必填
改文字:承認名字是選填 不輸入就用預設的「勇者」,降低進入門檻

我選了改程式。理由是:遊戲只有一個輸入框,連這個都不填就開打,那個輸入框存在的意義是什麼? 而且既然要做「最少回合紀錄」,名字是玩家在這個遊戲裡唯一的身分。

if (!state.ready) {
  addLog("請先輸入勇者名字,並按下「出征!」", "log-warning");
  nameInput.focus();
  return;
}

沿用 Day 25 學到的原則:擋下來,並且說明原因。而且多做一件事 —— focus() 把游標移到該填的地方。不只告訴玩家哪裡錯,還帶他過去。

插入 day26.png:再戰一次後直接按攻擊,被擋下並提示要先出征

遊戲說明:回收 Day 21 那個結論

Day 21 我找 bug 的時候,得到一個自己覺得最有價值的結論:

一個 bug 要能被「發現」,前提是有人知道「正確的行為應該是什麼」。

當時我說:血量變紅那個 bug,對一般玩家來說最難發現,因為「沒有遊戲說明,玩家不知道遊戲機制,不會覺得有問題」。

現在該還這筆債了。

<details id="howto">
  <summary>怎麼玩?</summary>
  <ul>...</ul>
</details>

<details> + <summary> 是 HTML 原生的摺疊區塊,點一下就展開,完全不需要 JavaScript。想看的人點開,不想看的人不會被佔版面。學了這麼多天的 JS,今天用一個純 HTML 標籤解決了問題,感覺有點好笑但也蠻好的。

插入 day26-2.png:展開的遊戲說明,以及戰鬥中的黃色血條

寫說明的時候,我發現自己漏了一條規則

初稿我寫:「血量低於三成時,血條會變紅」。

看完之後的反應是:要就寫全,不然就不寫。

因為血條其實有兩個門檻 —— 六成以下變黃、三成以下變紅。我只寫了紅色。

而漏掉的那個,正好是玩家最先看到的那個。如果只寫紅色,玩家看到血條變黃會困惑:「說明沒提到黃色,是不是壞了?」

不完整的說明,比沒有說明更糟 —— 因為它讓人以為自己掌握了全貌,於是把「說明沒寫到的東西」當成異常。

這件事讓我想通一個更普遍的道理:寫說明會逼你把隱含的規則講出來。那些「我知道,但從來沒寫下來」的規則,在動筆的時候才會浮出來。

而那正是 Day 21 說的:沒寫下來的規則,就是沒有人能驗證的規則。

但有些東西刻意不寫

寫說明的時候也遇到反方向的問題:要寫多細?

「傷害每次都會有些浮動」—— 要不要寫出範圍是多少?

我的判斷是不要。留一點空間讓玩家自己摸索,比把數字攤開來有趣。玩家會自己發現「同樣的攻擊,這次打 7 點、下次打 12 點」,那個發現本身就是遊戲體驗的一部分。

至於鞭屍那個彩蛋,說明裡一個字都沒提。寫出來就不叫彩蛋了。

所以說明的取捨其實有三層:

類型 處理
規則(操作方式、勝負條件、血條顏色) 寫,而且要寫全
數值細節(傷害範圍) 不寫,留給玩家摸索
彩蛋 完全不提

差別在於:規則是「不知道就會困惑」的東西,數值是「知道了反而無聊」的東西。

結果橫幅:讓勝負看得見

原本輸贏只有戰鬥紀錄裡的一行字,很容易滑過去。現在會出現一塊橫幅,勝利綠色、失敗紅色。

resultBox.hidden = false;   // 出現
resultBox.hidden = true;    // 藏起來

hidden 是 HTML 的標準屬性,比自己寫 style.display = "none" 更語意化 —— 而且螢幕閱讀器看得懂「這塊現在是隱藏的」,不會把它念出來。這算是接續昨天無障礙那個話題的一個小實踐。

我刻意沒做成蓋住畫面的彈窗。 因為那樣就按不到鞭屍了 —— 一個為了「儀式感」加的彈窗,會把已經存在的樂趣擋掉。

「再戰一次」該不該重新出征?我一開始想錯了

我原本的設計是:名字已經確認過了,再戰一次不用重新按出征,直接打就好 —— 少一個步驟,比較順。

但測試的時候發現一個陷阱:

再戰一次 → 輸入框解鎖了 → 玩家改了名字 → 但沒按出征
         → 直接按攻擊 → 第一次攻擊把輸入框鎖起來
         → 新名字永遠不會被讀取,而且再也改不掉

玩家會以為自己改了名字,實際上沒有。 而且畫面上的輸入框顯示的是新名字,血條旁邊顯示的是舊名字 —— 兩個地方對不起來。

所以改成每次再戰都要重新出征。多一個步驟,但換來一個保證:畫面上的名字,永遠等於實際使用的名字。

這個取捨我覺得值得:少一次點擊 vs 一個會讓人困惑又無法挽回的狀態,後者的代價大多了。

小結

今天搞懂的事:

  • 規格與實作不一致時,要先決定哪一邊是對的 —— 我選了讓程式遵守文字
  • 擋下操作時,順手 focus() 帶玩家到該處理的地方
  • <details> + <summary> 做摺疊說明,不需要任何 JavaScript
  • 寫說明會逼你把隱含的規則講出來 —— 我就是這樣才發現自己漏了黃色血條
  • 不完整的說明比沒有說明更糟,因為它讓人以為掌握了全貌
  • 說明要分層:規則寫全、數值留白、彩蛋不提
  • hidden 屬性比 style.display = "none" 更語意化
  • 不要用彈窗蓋住畫面 —— 那會把已經存在的互動擋掉
  • 少一個步驟 vs 一個無法挽回的困惑狀態,後者的代價大得多

遊戲的功能到這裡就完整了。明天開始收尾:排版、手機、還有一些我用 QA 眼睛看出來的小問題。


上一篇
Day25|我做出了一個會打人的屍體
下一篇
Day27|骰子與人性,賭性堅強與遊戲平衡
系列文
QA 的 JavaScript 初心之路:30 天做出一個能玩的戰鬥小遊戲《勇者 vs 小怪》 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言